/**
 * 智慧小区管理系统 - HTTP请求封装
 * 适配Sa-Token认证框架
 * @author Wu.Liang
 * @date 2024-01-01
 * @updated 2024-12-21 - 优化Token管理和错误处理
 * @updated 2024-12-22 - 适配Sa-Token认证框架
 * @updated 2025-01-30 - 修复401未登录响应处理，确保正确跳转到登录页面
 */
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, AxiosError, InternalAxiosRequestConfig } from 'axios'
import { ElMessage, ElLoading } from 'element-plus'
import { useUserStore } from '@/store/user'
import router from '@/router'
import { MESSAGES } from '@/constants/messages'
import { storeToRefs } from 'pinia'
import { processQueryParams, processFormParams } from '@/utils/request'

// 统一API响应结构
export interface ApiResponse<T = unknown> {
    code: number
    message: string
    data: T
    timestamp?: number
    success?: boolean
}

// 请求配置接口
interface RequestConfig extends AxiosRequestConfig {
    loading?: boolean
    errorMessage?: boolean
}

// 创建axios实例
const request: AxiosInstance = axios.create({
    baseURL: import.meta.env.VITE_API_BASE_URL || '/api',
    timeout: 15000, // 增加超时时间到15秒
    headers: {
        'Content-Type': 'application/json;charset=UTF-8'
    }
})

// 请求加载实例
let loadingInstance: any = null

// 请求拦截器
request.interceptors.request.use(
    (config: InternalAxiosRequestConfig) => {
        // 优先从localStorage读取token，保证header一定有
        const token = localStorage.getItem('token')
        if (token) {
            config.headers = config.headers || {}
            config.headers.Authorization = `Bearer ${token}`
        }

        // 简化客户端标识，避免触发CORS预检
        // 只在需要时添加客户端标识，对于简单的GET请求可以省略
        if (config.method !== 'get' || config.url?.includes('/upload') || config.url?.includes('/download')) {
            config.headers = config.headers || {}
            config.headers['X-Client-Type'] = 'web'
            config.headers['X-Client-Version'] = '1.0.0'
        }

        // 显示加载状态（对于非静默请求）
        if (!config.headers?.silent) {
            loadingInstance = ElLoading.service({
                lock: true,
                text: '加载中...',
                background: 'rgba(0, 0, 0, 0.7)'
            })
        }

        return config
    },
    (error: AxiosError) => {
        console.error('请求错误:', error)
        if (loadingInstance) {
            loadingInstance.close()
            loadingInstance = null
        }
        return Promise.reject(error)
    }
)

// 响应拦截器
request.interceptors.response.use(
    (response: AxiosResponse) => {
        // 关闭加载状态
        if (loadingInstance) {
            loadingInstance.close()
            loadingInstance = null
        }

        const { data, status } = response

        // 处理文件下载等特殊响应
        if (response.config.responseType === 'blob') {
            return response
        }

        // 检查HTTP状态码
        if (status !== 200) {
            ElMessage.error(`请求失败，状态码：${status}`)
            return Promise.reject(new Error(`HTTP Error: ${status}`))
        }

        // 检查业务状态码
        if (data.code !== undefined && data.code !== 200) {
            // 优先使用后端返回的错误消息，如果没有则使用默认消息
            const message = data.message || data.msg || '请求失败'

            // 处理特殊业务状态码
            switch (data.code) {
                case 401:
                case 40001:
                    handleUnauthorized(message)
                    break
                case 403:
                case 40003:
                    ElMessage.error(message)
                    break
                case 404:
                case 40004:
                    ElMessage.error(message)
                    break
                case 500:
                case 50000:
                    ElMessage.error(message)
                    break
                case 10001:
                    ElMessage.error(message)
                    break
                case 10002:
                    ElMessage.error(message)
                    break
                case 10003:
                    ElMessage.error(message)
                    break
                case 10004:
                    ElMessage.error(message)
                    break
                case 10005:
                    ElMessage.error(message)
                    break
                default:
                    ElMessage.error(message)
                    break
            }

            return Promise.reject(new Error(message))
        }

        return data
    },
    (error: AxiosError) => {
        // 关闭加载状态
        if (loadingInstance) {
            loadingInstance.close()
            loadingInstance = null
        }

        console.error('响应错误:', error)

        let message = '网络错误，请稍后重试'

        if (error.response) {
            const { status, data } = error.response as AxiosResponse<any>

            switch (status) {
                case 400:
                    message = data?.message || '请求参数错误'
                    break
                case 401:
                    // 处理401未登录响应
                    // 优先使用后端返回的错误消息，如果没有则使用默认消息
                    const unauthorizedMessage = data?.message || data?.msg || '登录已过期，请重新登录'
                    handleUnauthorized(unauthorizedMessage)
                    break
                case 403:
                    message = '权限不足，无法访问该资源'
                    break
                case 404:
                    message = '请求的资源不存在'
                    break
                case 408:
                    message = '请求超时，请稍后重试'
                    break
                case 500:
                    message = '服务器内部错误'
                    break
                case 502:
                    message = '网关错误'
                    break
                case 503:
                    message = '服务暂时不可用'
                    break
                case 504:
                    message = '网关超时'
                    break
                default:
                    message = data?.message || `请求失败，状态码：${status}`
                    break
            }
        } else if (error.request) {
            message = '网络连接失败，请检查网络设置'
        } else {
            message = error.message || '请求配置错误'
        }

        ElMessage.error(message)
        return Promise.reject(error)
    }
)

/**
 * 处理未授权响应
 * 统一处理401未登录情况，确保正确跳转到登录页面
 * @param message 错误消息
 */
const handleUnauthorized = async (message: string) => {
    console.log('处理未授权响应:', message)
    
    // 显示错误消息
    ElMessage.error(message)
    
    try {
        // 获取用户store实例
        const userStore = useUserStore()
        
        // 执行登出操作
        await userStore.userLogout()
        
        // 确保当前不在登录页面时才跳转
        const currentRoute = router.currentRoute.value
        if (currentRoute.path !== '/login') {
            console.log('跳转到登录页面')
            // 使用replace而不是push，避免在历史记录中留下当前页面
            await router.replace('/login')
        } else {
            console.log('当前已在登录页面，无需跳转')
        }
    } catch (error) {
        console.error('处理未授权响应时出错:', error)
        // 即使出错也要尝试跳转到登录页面
        try {
            await router.replace('/login')
        } catch (routerError) {
            console.error('跳转到登录页面失败:', routerError)
        }
    }
}

// 请求方法封装
const api = {
    get<T = any>(url: string, config?: AxiosRequestConfig): Promise<T> {
        // 处理GET请求的查询参数，过滤空值
        if (config?.params) {
            config.params = processQueryParams(config.params)
        }
        return request.get(url, config)
    },

    post<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> {
        // 处理POST请求的数据，过滤空值
        if (data) {
            data = processFormParams(data)
        }
        return request.post(url, data, config)
    },

    put<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> {
        // 处理PUT请求的数据，过滤空值
        if (data) {
            data = processFormParams(data)
        }
        return request.put(url, data, config)
    },

    delete<T = any>(url: string, config?: AxiosRequestConfig): Promise<T> {
        // 处理DELETE请求的查询参数，过滤空值
        if (config?.params) {
            config.params = processQueryParams(config.params)
        }
        return request.delete(url, config)
    },

    patch<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> {
        // 处理PATCH请求的数据，过滤空值
        if (data) {
            data = processFormParams(data)
        }
        return request.patch(url, data, config)
    },

    upload<T = any>(url: string, formData: FormData, config?: AxiosRequestConfig): Promise<T> {
        return request.post(url, formData, {
            ...config,
            headers: {
                'Content-Type': 'multipart/form-data',
                ...config?.headers
            }
        })
    },

    download(url: string, config?: AxiosRequestConfig): Promise<AxiosResponse<Blob>> {
        // 处理下载请求的查询参数，过滤空值
        if (config?.params) {
            config.params = processQueryParams(config.params)
        }
        return request.get(url, {
            ...config,
            responseType: 'blob'
        })
    }
}

export default api
export { request }
